﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Control;
using Model;
using System.Drawing.Printing;
using System.Drawing.Text;
using System.IO;


namespace PJRScrum
{
    public partial class PJRGUI : Form
    {
        #region Fields
        private Image achtergrond;
        private double zoompercentage;
        private Winkel winkel; //De aangemaakte plattegrond inclusief reagge!
        private View view;
        private bool PJRBestandGeladen;
        private bool radioButtonBedragPrijsGeselecteerd;

        //Printen
        private List<string> printLijst;
        private int printI;
        private bool firstPage = true;

        //Algoritme variabelen
        private List<string> categoriën;
        private double snelheid;
        private int tijd;
        private int bedrag; //TODO: invulling geven

        //Penalty variabelen
        private double euroPen;
        private double tijdPen;
        private double factor;
        #endregion

        public PJRGUI()
        {
            InitializeComponent();
            view = View.GetInstance();
            LaadCategorie();
            winkel = Winkel.GetInstance();
            SetToolTipInfo();
            gBCategorie.Enabled = false;
        }

        private void SetToolTipInfo()
        {
            ToolTip toolTip1 = new ToolTip();

            toolTip1.AutoPopDelay = 5000;
            toolTip1.InitialDelay = 300;
            toolTip1.ReshowDelay = 500;
            toolTip1.ShowAlways = true;

            toolTip1.SetToolTip(buttonBerekenen, "Hiermee zal de computer de best mogelijke route berekenen!");
            toolTip1.SetToolTip(buttonKassa, "De producten die u moet pakken zijn zichtbaar in de kassa");
            toolTip1.SetToolTip(btnLaden, "Als u al over een plattegrond beschikt kunt u deze hiermee laden");
            toolTip1.SetToolTip(btnImport, "Hier kunt u een nieuwe plattegrond van een winkel creëren");
            toolTip1.SetToolTip(btnZoomIn, "Inzoomen op de plattegrond");
            toolTip1.SetToolTip(btnZoomOut, "Uitzoomen op de plattegrond");
            toolTip1.SetToolTip(buttonPrint, "Print de route met de benodigde artikelen via uw eigen printer");
            toolTip1.SetToolTip(buttonSluiten, "Hiermee sluit u deze applicatie");
            toolTip1.SetToolTip(gBCategorie, "Selecteer de categoriën die u wilt betrekken in uw route");
            toolTip1.SetToolTip(gBInstellingen, "Stel de gegevens na uw wens in");
            toolTip1.SetToolTip(radioButtonBedrag, "Selecteer bedrag als invoer");
            toolTip1.SetToolTip(radioButtonTijd, "Selecteer tijd als invoer");
            toolTip1.SetToolTip(trackBarTijd, "Selecteer de tijd in seconde");
            toolTip1.SetToolTip(trackBarSnelheid, "Selecteer de snelheid in km/h");
            toolTip1.SetToolTip(trackBarBedrag, "Selecteer het bedrag in euro");

        }

        #region Categorie groupbox

        /// <summary>
        /// Categoriën laden in checkboxes.
        /// </summary>
        private void LaadCategorie()
        {
            List<string> lijst = view.LaadCategorie();
            for (int i = 0; i < lijst.Count; i++)
            {
                CheckBox c = new CheckBox();
                c.Text = lijst[i].ToString();
                c.Name = "textbox" + lijst[i].ToString();
                c.CheckedChanged += new EventHandler(c_CheckedChanged);
                c.Location = new Point(20, 20 + i * 22);
                gBCategorie.Controls.Add(c);
            }
        }

        /// <summary>
        /// Wordt aangeroepen bij een wijziging van een checkbox
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void c_CheckedChanged(object sender, EventArgs e)
        {
            categoriën = new List<string>();
            foreach (CheckBox cb in gBCategorie.Controls)
            {
                if (cb.Checked == true)
                {
                    categoriën.Add(cb.Text);
                    gBInstellingenCheck();
                }
            }
            if (categoriën.Count == 0) //Geen items aangevinkt, instellingen worden dan niet beschikbaar gemaakt.
            {
                gBInstellingen.Enabled = false;
                buttonBerekenen.Enabled = false;
            }
        }
        private void gBInstellingenCheck()
        {
            if (PJRBestandGeladen)
            {
                gBInstellingen.Enabled = true;
            }
        }

        #endregion

        #region Instellingen groupbox


        /// <summary>
        /// Verander de trackbars o.b.v. prijs of bedrag invoer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void radioButton_BedragPrijs(object sender, EventArgs e)
        {
            //buttonBerekenen.Enabled = true;
            if (radioButtonBedrag.Checked)
            {
                //Trackbars
                labelSnelheid.Text = "Loopsnelheid (" + trackBarSnelheid.Value.ToString() + " Km/h)";
                trackBarBedrag.Enabled = true;
                labelBedrag.Text = "Bedrag (" + trackBarBedrag.Value.ToString() + " Euro)";
                trackBarTijd.Enabled = false; 
                trackBarTijd.Value = trackBarTijd.Minimum;
                labelTijd.Text = "Tijd";
                //Textboxes
                tbStraftijdSeconde.Enabled = true;
                tbStraftijdEuro.Enabled = true;
                //Rest
                buttonBerekenen.Enabled = false;
                radioButtonBedragPrijsGeselecteerd = true;
                View.GetInstance().VeranderAlgoritme(TypeAlgoritme.Bedrag);
            }
            else
            {
                //Trackbars
                trackBarBedrag.Enabled = false;
                trackBarBedrag.Value = trackBarBedrag.Minimum; 
                labelBedrag.Text = "Bedrag";
                trackBarTijd.Enabled = true;
                trackBarTijd.Value = trackBarTijd.Minimum;
                labelTijd.Text = "Tijd (" + trackBarTijd.Value.ToString() + " Seconde)";

                //Textboxes
                tbStraftijdSeconde.Enabled = false;
                tbStraftijdSeconde.Text = "";
                tbStraftijdEuro.Enabled = false;
                tbStraftijdEuro.Text = "";

                buttonBerekenen.Enabled = true;
                radioButtonBedragPrijsGeselecteerd = true;
                View.GetInstance().VeranderAlgoritme(TypeAlgoritme.Tijd);
            }
        }

        /// <summary>
        /// Geef de ingestelde waarde weer op het form.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trackBarInstellingen_Scroll(object sender, EventArgs e)
        {
            if ((sender as TrackBar) == trackBarSnelheid)
            {
                labelSnelheid.Text = "Loopsnelheid (" + trackBarSnelheid.Value.ToString() + " Km/h)";
                snelheid = trackBarSnelheid.Value;
            }
            else if ((sender as TrackBar) == trackBarBedrag)
            {
                labelBedrag.Text = "Bedrag (" + trackBarBedrag.Value.ToString() + " Euro)";
                bedrag = trackBarBedrag.Value;
            }
            else if ((sender as TrackBar) == trackBarTijd)
            {
                labelTijd.Text = "Tijd (" + trackBarTijd.Value.ToString() + " Seconde)";
                tijd = trackBarTijd.Value;
            }
        }

        private void tbStraftijdEuro_Leave_1(object sender, EventArgs e)
        {
            try
            {
                euroPen = Convert.ToDouble(tbStraftijdEuro.Text);
            }
            catch
            {
                MessageBox.Show("Dit is geen geldige invoer.", "Input error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                (sender as TextBox).Text = "";
            }
        }

        private void tbStraftijdSeconde_Leave(object sender, EventArgs e)
        {
            try
            {
                tijdPen = Convert.ToDouble(tbStraftijdSeconde.Text);
            }
            catch
            {
                MessageBox.Show("Dit is geen geldige invoer.", "Input error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                (sender as TextBox).Text = "";
            }
            if (tbStraftijdEuro.Text != "")
            {
                factor = euroPen / tijdPen;
                buttonBerekenen.Enabled = true;
            }
        }


        #endregion

        #region Zoomen en scrollen van de plattegrond
        private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            schuiven((-vScrollBar1.Value), pbPlattegrond.Left);
        }

        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            schuiven(pbPlattegrond.Top, (-hScrollBar1.Value));
        }

        private void btnZoomIn_Click(object sender, EventArgs e)
        {
            if (zoompercentage < 250)
            {
                zoompercentage += 10;
                Zoom();
            }

        }

        private void btnZoomOut_Click(object sender, EventArgs e)
        {
            if (zoompercentage > 10) { zoompercentage -= 10; Zoom(); }

        }

        /// <summary>
        /// Regelt het verschuiven van de plattegrond
        /// </summary>
        /// <param name="Top">Hoeveel er vanuit de top verschoven moet worden</param>
        /// <param name="Left">Hoeveel er vanuit de linker zijde verschoven moet worden</param>
        private void schuiven(int Top, int Left)
        {
            pbPlattegrond.Top = Top;
            pbPlattegrond.Left = Left;
        }

        /// <summary>
        /// Zoomt in met de algemene zoomfactor
        /// </summary>
        private void Zoom()
        {
            if (achtergrond != null)
            {
                Bitmap img = new Bitmap(view.Plattegrond, getZoomFormaat());
                int hPercentage = hScrollBar1.Maximum;
                int vPercentage = vScrollBar1.Maximum;
                PlattegrondTonen(img);
                vScrollBar1.Value = (vScrollBar1.Value * vScrollBar1.Maximum) / vPercentage;
                hScrollBar1.Value = (hScrollBar1.Value * hScrollBar1.Maximum) / hPercentage;
                schuiven(-vScrollBar1.Value, -hScrollBar1.Value);
            }
        }

        private Size getZoomFormaat()
        {
            return new Size((int)((zoompercentage / 100) * achtergrond.Width), (int)((zoompercentage / 100) * achtergrond.Height));
        }

        delegate void PlattegrondVeranderen(Image img);
        /// <summary>
        /// Toont de gegeven afbeelding op het plattegrond vlak.
        /// </summary>
        /// <param name="image">De plattergrond</param>
        private void PlattegrondTonen(Image image)
        {
            if (this.InvokeRequired)
            {
                PlattegrondVeranderen p = new PlattegrondVeranderen(PlattegrondTonen);
                this.Invoke(p, new Object[] { image});
                return;
            }
            if (view.Beste != null)
            {
                Winkelwagen w = view.Beste;
                Graphics tempGraphics = Graphics.FromImage(image);
                Pen p = new Pen(Color.Green);
                p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
                for (int i = 0; i < w.AfgelegdeWeg.Count - 1; i++)
                {
                    if (w.AfgelegdeWeg[i] == null || w.AfgelegdeWeg[i + 1] == null)
                    {
                        continue;
                    }
                    Point p1 = DaadwerkelijkNaarRelatief(w.AfgelegdeWeg[i].Plaats);
                    Point p2 = DaadwerkelijkNaarRelatief(w.AfgelegdeWeg[i + 1].Plaats);
                    tempGraphics.DrawLine(p, p1, p2);
                }
            }
            if (image == null)
                return;
            btnZoomIn.Visible = true;
            btnZoomOut.Visible = true;
            if (panel1.Height <= image.Height)
            {
                vScrollBar1.Maximum = image.Height - panel1.Height;
                vScrollBar1.Visible = true;
            }
            else { vScrollBar1.Visible = false; }
            if (panel1.Width <= image.Width)
            {
                hScrollBar1.Maximum = image.Width - panel1.Width;
                hScrollBar1.Visible = true;
            }
            else { hScrollBar1.Visible = false; }
            pbPlattegrond.Image = image;
            
        }

        private Point DaadwerkelijkNaarRelatief(Point plaats)
        {
            plaats.Y = (int)((plaats.Y * zoompercentage) / 100);
            plaats.X = (int)((plaats.X * zoompercentage) / 100);
            return plaats;
        }
        #endregion

        #region Buttons



        private void btnImport_Click(object sender, EventArgs e)
        {
            NewImportGui importGui = new NewImportGui();
            importGui.ShowDialog();
            gBCategorie.Enabled = true;
            PJRBestandGeladen = true;
            PlattegrondLaden(winkel.Plattegrond);
            zoompercentage = 100;
            //Haal info van winkel op via interface
            //Zet de afbeelding neer in de picturebox
        }

        private void buttonKassa_Click(object sender, EventArgs e)
        {
            Winkelwagen winkel = view.Beste;
            KassaGUI kassa = new KassaGUI(winkel.Totaalprijs, winkel.Volume, winkel.Inhoud);
            kassa.ShowDialog();
        }

        private void buttonSluiten_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        ProgressForm progressForm;
        private void buttonBerekenen_Click(object sender, EventArgs e)
        {
            snelheid = trackBarSnelheid.Value / 3.6;
            tijd = trackBarTijd.Value;
            bedrag = trackBarBedrag.Value;
            factor = bedrag / tijd;
            view.BerekenRoute(categoriën, (int)snelheid, tijd, bedrag, factor);
            view.OplossingErbij += new EventHandler(view_OplossingErbij);
            view.BesteOplossingGevonden += new EventHandler(view_BesteOplossingGevonden);
            progressForm = new ProgressForm();
            progressForm.Stoppen += new EventHandler(progressForm_Stoppen);
            progressForm.ShowDialog();
            buttonKassa.Enabled = true;
            buttonPrint.Enabled = true;
        }

        void view_BesteOplossingGevonden(object sender, EventArgs e)
        {
            view = View.GetInstance();
            view.BesteOplossingGevonden -= view_BesteOplossingGevonden;
            view.OplossingErbij -= view_OplossingErbij;
            progressForm.sluit();
            Winkelwagen w = sender as Winkelwagen;
            Bitmap temp = new Bitmap(view.Plattegrond.Width, view.Plattegrond.Height);
            Graphics tempGraphics = Graphics.FromImage(temp);
            tempGraphics.DrawImage(view.Plattegrond, 0, 0);
            Pen p = new Pen(Color.Green);
            p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
            for (int i = 0; i < w.AfgelegdeWeg.Count - 1; i++)
            {
                if (w.AfgelegdeWeg[i] == null || w.AfgelegdeWeg[i + 1] == null)
                {
                    continue;
                }
                Point p1 = w.AfgelegdeWeg[i].Plaats;
                Point p2 = w.AfgelegdeWeg[i + 1].Plaats;
                tempGraphics.DrawLine(p, p1, p2);
            }
            PlattegrondTonen(temp);
        }

        void progressForm_Stoppen(object sender, EventArgs e)
        {
            View.GetInstance().StopAlgoritme();
        }

        delegate void SetTextCallback(string text);
        void view_OplossingErbij(object sender, EventArgs e)
        {
            setText((++progressForm.aantal).ToString());
        }

        void setText(string text)
        {
            if (progressForm != null)
            {
                if (progressForm.lblAant.InvokeRequired)
                {
                    SetTextCallback d = new SetTextCallback(setText);
                    this.Invoke(d, new object[] { text });
                }
                else
                {
                    progressForm.lblAant.Text = text;
                }
            }
        }

        #region Printen
        /// <summary>
        /// Moet nog aangepast geworden!
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonPrint_Click(object sender, EventArgs e)
        {
            //Nog veranderen zodat er ook een lijst met artikelen beschikbaar is in het winkelwagen
            if (winkel.Plattegrond != null)
            {
                List<string> lijst = new List<string>();
                foreach (Artikel product in winkel.BesteUitkomst.Inhoud)
                {
                    lijst.Add(product.ToString());
                }
                Printen(winkel.Plattegrond, lijst);
            }
            else
            {
                MessageBox.Show("Printen is niet mogelijk als u nog geen route heeft laten berekenen!", "Fout!",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Printen(Image image, List<string> artikelen)
        {
            //Printdocument afbeelding
            PrintDocument routePrint = new PrintDocument { DocumentName = "De route voor uw winkel!" };
            routePrint.PrintPage += printDocument_PrintPage;

            //Preview
            PrintPreviewDialog dialog = new PrintPreviewDialog();
            ((ToolStrip)dialog.Controls[1]).Items[0].Visible = false; //Printknop vanuit preview niet zichtbaar
            ((Form)dialog).WindowState = FormWindowState.Maximized;  //Maximaliseer het venster
            dialog.Document = routePrint;
            dialog.ShowDialog();

            //Zodra de preview afgesloten wordt, zal het printvenster verschijnen.

            //Printdialog
            PrintDialog printDialog = new PrintDialog();
            printDialog.Document = routePrint;
            printDialog.Document.PrintPage += printDocument_PrintPage;
            printDialog.ShowDialog();
        }

        /// <summary>
        /// Eventhandler voor het printen van de route
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void printDocument_PrintPage(object sender, PrintPageEventArgs e)
        {
            if (firstPage)
            {
                printI = 0;
                e.Graphics.DrawImage(winkel.Plattegrond, 0, 0, e.PageSettings.PaperSize.Width,
                                     e.PageSettings.PaperSize.Height); //Fullscreen printen van de plattegrond
                e.HasMorePages = true;
                firstPage = false;
            }
            else
            {
                float linesPerPage = e.MarginBounds.Height / this.Font.GetHeight(e.Graphics);
                string line = "";
                float leftMargin = e.MarginBounds.Left;
                float topMargin = e.MarginBounds.Top;
                int count = 0;

                while ((count < linesPerPage) && (printI < printLijst.Count))
                {
                    line = printLijst[printI];
                    float yPos = topMargin + (count * this.Font.GetHeight(e.Graphics));
                    e.Graphics.DrawString(printLijst[count], this.Font, Brushes.Black, leftMargin, yPos, new StringFormat());
                    count++;
                    printI++;
                }
                if (printI < printLijst.Count)
                    e.HasMorePages = true;
                else
                {
                    e.HasMorePages = false;
                    printI = 0;
                    firstPage = true;
                }
            }
        }
        #endregion

        private void btnLaden_Click(object sender, EventArgs e)
        {
            Serializer serializer = new Serializer();
            ObjectToSerialize ots;
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Title = "Open plattegrond";
            ofd.Filter = "PJR bestand|*.pjr";
            ofd.InitialDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            string pad = "";

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                pad = ofd.FileName;
                ots = serializer.DeSerializeObject(pad);
                Winkel.Instance = ots.Winkel;
                winkel = Winkel.GetInstance();
                PlattegrondLaden(winkel.Plattegrond);
                AbstracteLaag.Instance = winkel.abstracteLaag;
            }
            gBCategorie.Enabled = true;
            PJRBestandGeladen = true;
        }

        private void PlattegrondLaden(Image image)
        {
            pbPlattegrond.Image = image;
            achtergrond = image;
            PlattegrondTonen(achtergrond);
            zoompercentage = 100;
        }
        #endregion

        private void PJRGUI_Load(object sender, EventArgs e)
        {

        }

        

        

        



    }
}
